package com.bgds.sys.data.iXCom29d.gateway.impl;

import cn.hutool.core.util.NumberUtil;
import com.cisdi.data.common.exception.BusinessException;
import com.mchange.lang.IntegerUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.nio.charset.Charset;
import java.util.List;

/**
 * @author
 */
public class BaoXingFrameDecoder extends ByteToMessageDecoder {


    /**
     * 30 byte 长度报文头
     */
    private static final short MIN_LENGTH = 30;

    /**
     * 4 byte 长度，最大允许4030 Byte,防止攻击
     */
    //private static final short MAX_LENGTH = 4030;

    private static final short MAX_LENGTH = 8889;

    Charset charset = null;

    public BaoXingFrameDecoder(Charset charset) {
        this.charset = charset;
    }


    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf bufferIn, List<Object> out) throws Exception {
        if (bufferIn.readableBytes() < MIN_LENGTH) {
            return;
        }
        final int beginIndex = bufferIn.readerIndex();
        //获取电文TELELENGTH telelength
        byte[] headerBytes = new byte[4];
        bufferIn.readBytes(headerBytes);
        String header = new String(headerBytes, charset);
        // 电文总长度
        String lengthString = getString(header, 0, 4);
        if (lengthString != null) {
            //int length = Integer.valueOf(lengthString);
            int length = NumberUtil.parseInt(lengthString);
            if (length > MAX_LENGTH) {
                ctx.close();
                throw new BusinessException("超过协议允许最大报文长度，默认为 " + MAX_LENGTH + " byte，当前为" + length + "byte");
            }
            if (length < MIN_LENGTH) {
                ctx.close();
                throw new BusinessException(ctx.channel().toString() + "传输数据体长度小于30， 此长度为:" + length);
            }
            // 拆包
            if (bufferIn.readableBytes() < length - 4) {
                bufferIn.readerIndex(beginIndex);
                return;
            }

            bufferIn.readerIndex(beginIndex);

            ByteBuf otherByteBufRef = bufferIn.retainedSlice(beginIndex, length);

            bufferIn.readerIndex(beginIndex + length);

            out.add(otherByteBufRef);

            // 处理可能的粘包
            decode(ctx, bufferIn, out);
        }

    }

    private String getString(String header, int start, int end) {
        char[] dst = new char[end - start];
        header.getChars(start, end, dst, 0);
        return new String(dst);
    }
}
